#include "customhandler.h"
#include <QDebug>
CustomHandler* CustomHandler::handler=nullptr;
QHash<QString,QByteArray> CustomHandler::hash=QHash<QString,QByteArray>();
QString CustomHandler::useroc=QString();
static  QString cachepath=QString();
static  QString avatarpath=QString();
CustomHandler *CustomHandler::getInstance()
{
    if(!handler)
    {
        handler=new CustomHandler;
        hash["friendinfo"]="recvFriendInfo";
        hash["friendapplyaccess"]="friendApplyAccess";
        hash["friendapply"]="haveFriendApply";
        hash["contactlist"]="analysisContactList";
        hash["userinfo"]="recvUserInfo";
        hash["contactlistend"]="contactlistEnd";
        hash["fileblock"]="dealFileBlock";
    }
    return handler;
}

void CustomHandler::setUseroc(const QString &useroc)
{
    CustomHandler::useroc=useroc;
    cachepath=QString("./User/%1/Cache/").arg(useroc);
    avatarpath=QString("./User/%1/Avatar/").arg(useroc);
}

void CustomHandler::handle(const QByteArray &arr)
{
    //分割出类型
    uint8_t firstindex=arr.indexOf("#$^");
    uint8_t secondindex=arr.indexOf("#$^",firstindex+1);
    QString type=arr.mid(firstindex+3,secondindex-3);
    QByteArray payload=arr.mid(secondindex+3);
    if(hash.contains(type))
    {
        //分割出参数，生成参数列表
        QByteArrayList arglist=splitStringUsingKMP(payload,"#$^");
        handler->metaObject()->invokeMethod(handler, hash[type].data(), Q_ARG(const QByteArrayList&,arglist));
    }
    else
    {
        qDebug()<<"no contains "<<type;
    }

}

void CustomHandler::recvFriendInfo(const QByteArrayList& arglist)
{

    QString friendname=arglist[0];

    QFile file(cachepath+friendname+".png");

    if(!file.open(QIODevice::WriteOnly))
    {
        qDebug()<<"open file failed";
        return;
    }
    file.write(arglist[1]);
    emit s_recvFriendInfo(friendname);
}

void CustomHandler::friendApplyAccess(const QByteArrayList &arglist)
{
    QString friendoc=arglist[0];
    QString friendname=arglist[1];
    QFile file(avatarpath+friendoc+".png");
    if(!file.open(QIODevice::WriteOnly))
    {
        qDebug()<<"open file failed";
    }
    file.write(arglist[2]);
    emit s_friendApplyAccess(friendoc,friendname);
}

void CustomHandler::haveFriendApply(const QByteArrayList &arglist)
{
    QString friendoc=arglist[0];
    QString friendname=arglist[1];
    QFile file(cachepath+friendoc+".png");
    if(!file.open(QIODevice::WriteOnly))
    {
        qDebug()<<"open file failed";
    }
    file.write(arglist[2]);
    emit s_haveFriendApply(friendoc,friendname,EnumLib::ApplyStatus::UNDERREVIEW);
}

void CustomHandler::analysisContactList(const QByteArrayList &arglist)
{
    QString friendoc=arglist[0];
    QString friendname=arglist[1];
    QFile file(avatarpath+friendoc+".png");
    if(!file.open(QIODevice::WriteOnly))
    {
        qDebug()<<"open file failed";
    }
    file.write(arglist[2]);
    contactlist.append(QPair<QString,QString>(friendoc,friendname));
    emit s_recvOneContact();
    //qDebug()<<"emit signal";
}

void CustomHandler::recvUserInfo(const QByteArrayList &arglist)
{
    QString username=arglist[0];
    QFile file(avatarpath+"user.png");
    if(!file.open(QIODevice::WriteOnly))
    {
        qDebug()<<"open file failed";
    }
    file.write(arglist[1]);
    emit s_recvUserInfo(username);
}

void CustomHandler::contactlistEnd(const QByteArrayList& arglist)
{
    emit s_recvContactlistDone(contactlist);
    contactlist.clear();
}

void CustomHandler::dealFileBlock(const QByteArrayList &arglist)
{
    emit s_fileBlock(arglist[0],arglist[1],arglist[2]);
}

CustomHandler::CustomHandler(){}
std::vector<int> CustomHandler::computeLPSArray(const QByteArray &pattern)
{
    int M = pattern.length();
    std::vector<int> lps(M, 0);
    int len = 0;

    lps[0] = 0; // lps[0] is always 0
    int i = 1;

    while (i < M)
    {
        if (pattern[i] == pattern[len])
        {
            len++;
            lps[i] = len;
            i++;
        }
        else
        {
            if (len != 0)
            {
                len = lps[len - 1];
            }
            else
            {
                lps[i] = 0;
                i++;
            }
        }
    }
    return lps;
}

std::vector<int> CustomHandler::KMPSearch(const QByteArray &text, const QByteArray &pattern)
{
    int N = text.length();
    int M = pattern.length();
    std::vector<int> lps = computeLPSArray(pattern);
    std::vector<int> indices;

    int i = 0; // index for text[]
    int j = 0; // index for pattern[]

    while (i < N)
    {
        if (pattern[j] == text[i])
        {
            j++;
            i++;
        }

        if (j == M)
        {
            indices.push_back(i - j);
            j = lps[j - 1];
        }
        // mismatch after j matches
        else if (i < N && pattern[j] != text[i])
        {
            // Do not match lps[0...lps[j-1]] characters,
            // they will match anyway
            if (j != 0)
                j = lps[j - 1];
            else
                i = i + 1;
        }
    }
    return indices;
}


int CustomHandler::KMPSIndexOf(const QByteArray &text, const QByteArray &pattern,const int startIndex)
{
    int N = text.length();
    int M = pattern.length();
    std::vector<int> lps = computeLPSArray(pattern);
    std::vector<int> indices;

    int i = startIndex; // index for text[]
    int j = 0; // index for pattern[]

    while (i < N)
    {
        if (pattern[j] == text[i])
        {
            j++;
            i++;
        }

        if (j == M)
        {
            return i - j;
        }
        // mismatch after j matches
        else if (i < N && pattern[j] != text[i])
        {
            // Do not match lps[0...lps[j-1]] characters,
            // they will match anyway
            if (j != 0)
                j = lps[j - 1];
            else
                i = i + 1;
        }
    }
    return -1;
}

QByteArrayList CustomHandler::splitStringUsingKMP(const QByteArray &mainString, const QByteArray &delimiter)
{
    std::vector<int> matchIndices = KMPSearch(mainString, delimiter);
    QByteArrayList resultList;

    int startIndex = 0;
    for (int index : matchIndices)
    {
        resultList.append(mainString.mid(startIndex, index - startIndex));
        startIndex = index + delimiter.length();
    }

    resultList.append(mainString.mid(startIndex));

    return resultList;
}
